package com.ztbsuper.dingding;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import hudson.ProxyConfiguration;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.scm.ChangeLogSet;
import jenkins.model.Jenkins;

/**
 * 
 * @author rubekid
 *
 * 2017年6月27日 下午11:16:38
 */
@SuppressWarnings("rawtypes")
public class DingdingServiceImpl implements DingdingService {

    private Logger logger = LoggerFactory.getLogger(DingdingService.class);

    private static final String DEFAULT_ICON = "http://static.xcx0592.com/jenkins/jenkins.jpg";
    
    private static final String API_URL = "https://oapi.dingtalk.com/robot/send?access_token=";

    /**
     * 配置信息
     */
    private JenkinsConfig config;
    
    
    private TaskListener listener;

    
	private AbstractBuild build;


    
    private String icon;

    public DingdingServiceImpl( JenkinsConfig config, TaskListener listener, AbstractBuild build) {
    	this.config = config;
        this.listener = listener;
        this.build = build;
        this.icon = config.getIcon();
        if(this.icon == null || "".equals(this.icon)){
        	this.icon = DEFAULT_ICON;
        }
    }

    @Override
    public void start() {
        String title = String.format("%s%s开始构建", build.getProject().getDisplayName(), build.getDisplayName());
        String content = String.format("项目[%s%s]开始构建", build.getProject().getDisplayName(), build.getDisplayName());

        String link = getBuildUrl();
        if (config.isOnStart()) {
            sendLinkMessage(title, content, icon, link);
        }

    }

    private String getBuildUrl() {
    	String jenkinsUrl = config.getJenkinsURL();
        if (jenkinsUrl.endsWith("/")) {
            return jenkinsUrl + build.getUrl();
        } else {
            return jenkinsUrl + "/" + build.getUrl();
        }
    }

    @Override
    public void success() {
        String title = String.format("%s%s发布成功", build.getProject().getDisplayName(), build.getDisplayName());
        String template = config.getTemplate();
        if(template == null || "".equals(template)){
        	template = "发布详情:{content}, 耗时:{duration}";
        }
        String content = template.replace("{content}", getChangeLog(build.getChangeSet()))
        		.replace("{duration}",  build.getDurationString());
        
        if (config.isOnSuccess()) {
        	if(config.isUseActionCard()){        		
        		sendActionCardMessage(title, content, config.getRedirectURL());
        	}
        	else{        		
        		sendLinkMessage(title, content, icon,  config.getRedirectURL());
        	}
        }
    }

    @Override
    public void failed() {
        String title = String.format("%s%s构建失败", build.getProject().getDisplayName(), build.getDisplayName());
        String content = String.format("项目[%s%s]构建失败, summary:%s, 耗时:%s", build.getProject().getDisplayName(), build.getDisplayName(), build.getBuildStatusSummary().message, build.getDurationString());
        String link = getBuildUrl();
        if (config.isOnFailed()) {
            logger.info("send link msg from " + listener.toString());
            sendLinkMessage(title, content, icon, link);
        }
    }
    
    /**
     * 卡片消息
     * @param title
     * @param content
     * @param link
     */
    private void sendActionCardMessage(String title, String content, String link){
         JSONObject body = new JSONObject();
         body.put("msgtype", "actionCard");
         JSONObject actionCardObject = new JSONObject();
         actionCardObject.put("title", title);
         actionCardObject.put("text", content);
         actionCardObject.put("hideAvatar", "0");
         actionCardObject.put("btnOrientation", "0");
         actionCardObject.put("singleTitle", "查看效果");
         actionCardObject.put("singleURL", link);
         body.put("actionCard", actionCardObject);
         send(body);

    }

    /**
     * 链接消息
     * @param title
     * @param content
     * @param icon
     * @param link
     */
    private void sendLinkMessage(String title, String content, String icon,  String link) {
        JSONObject body = new JSONObject();
        body.put("msgtype", "link");
        JSONObject linkObject = new JSONObject();
        linkObject.put("text", content);
        linkObject.put("title", title);
        linkObject.put("picUrl", icon);
        linkObject.put("messageUrl", link);
        body.put("link", linkObject);
        send(body);
    }
    
    /**
     * 发送消息
     * @param body
     */
    private void send(JSONObject body){
    	String[] accessTokens = config.getAccessToken().split(";");
    	for(String accessToken : accessTokens){
    		String apiUrl = API_URL + accessToken;
    		send(body, apiUrl);
    	}	
    }
    
    /**
     * 发送消息
     * @param body
     * @param apiUrl
     */
    private void send(JSONObject body, String apiUrl){
    	 HttpClient client = getHttpClient();
         PostMethod post = new PostMethod(apiUrl);
         try {
             post.setRequestEntity(new StringRequestEntity(body.toJSONString(), "application/json", "UTF-8"));
         } catch (UnsupportedEncodingException e) {
             e.printStackTrace();
             logger.error("build request error", e);
         }
         try {
             client.executeMethod(post);
             logger.info(post.getResponseBodyAsString());
         } catch (IOException e) {
             logger.error("send msg error", e);
         }
         post.releaseConnection();
    }


    private HttpClient getHttpClient() {
        HttpClient client = new HttpClient();
        Jenkins jenkins = Jenkins.getInstance();
        if (jenkins != null && jenkins.proxy != null) {
            ProxyConfiguration proxy = jenkins.proxy;
            if (proxy != null && client.getHostConfiguration() != null) {
                client.getHostConfiguration().setProxy(proxy.name, proxy.port);
                String username = proxy.getUserName();
                String password = proxy.getPassword();
                if (username != null && !"".equals(username.trim())) {
                    logger.info("Using proxy authentication (user=" + username + ")");
                    client.getState().setProxyCredentials(AuthScope.ANY,
                            new UsernamePasswordCredentials(username, password));
                }
            }
        }
        return client;
    }
   
    /**
     * 获取提交信息
     * @param cs
     * @return
     */
    private String getChangeLog(ChangeLogSet<?> cs) {
    	DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	StringBuilder sb = new  StringBuilder();
    	for (Object o : cs) {
            ChangeLogSet.Entry e = (ChangeLogSet.Entry) o;
            sb.append(String.format("%s提交：%s[%s]%n", e.getAuthor(), e.getMsg(), df.format(new Date(e.getTimestamp()))));
        }
    	return sb.toString();
    }

}
